package com.unitd.frame.comm.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @desc 日期工具类
 * @filename DateUtils.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/11/13
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

	public static final String DATE_PATTERN = "yyyy-MM-dd";
	public static final String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
	private static final Object timestampFormatLock = new Object();
	private static final Map<String, ThreadLocal<SimpleDateFormat>> timestampFormatPool = new HashMap<>();

	/**
	 * @desc 获取格式化时间对象
	 * @return SimpleDateFormat
	 */
	private static SimpleDateFormat getTimestampFormat() {
		ThreadLocal<SimpleDateFormat> thread = timestampFormatPool.get(TIMESTAMP_PATTERN);
		if (null == thread) {
			synchronized (timestampFormatLock) {
				thread = timestampFormatPool.get(TIMESTAMP_PATTERN);
				if (null == thread) {
					thread = new ThreadLocal<SimpleDateFormat>() {
						@Override
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(TIMESTAMP_PATTERN);
						}
					};
					timestampFormatPool.put(TIMESTAMP_PATTERN, thread);
				}
			}
		}
		return thread.get();
	}

	/**
	 * @desc 根据制定的时间格式,获取该格式下的当前时间对象
	 * @param formater 支持的时间格式
	 * @return
	 */
	public static Date getCurrDate(String formater) {
		Date currDate = null;
		try {
			if(StringUtils.isNull(formater)) formater = TIMESTAMP_PATTERN;

			SimpleDateFormat sdf = new SimpleDateFormat(formater);
			currDate = sdf.parse(sdf.format(new Date()));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return currDate;
	}

	/**
	 * @desc 获取一天开始时间
	 * @param date 指定日期
	 * @return Date
	 */
	public static Date getDayBegin(Date date) {
		String format = DateFormatUtils.format(date, DATE_PATTERN);
		return parseDate(format.concat(" 00:00:00"));
	}

	/**
	 * @desc 获取一天结束时间
	 * @param date 指定日期
	 * @return Date
	 */
	public static Date getDayEnd(Date date) {
		String format = DateFormatUtils.format(date, DATE_PATTERN);
		return parseDate(format.concat(" 23:59:59"));
	}


	/**
	 * @desc 比较两个时间相差多少秒
	 * @param start 需要比较的开始时间
	 * @param end 需要比较的结束时间
	 * @return
	 */
	public static long getDiffSeconds(Date start, Date end) {
		return Math.abs((end.getTime() - start.getTime()) / 1000);
	}

	/**
	 * @desc 比较两个时间相差多少分钟
	 * @param start 需要比较的开始时间
	 * @param end 需要比较的结束时间
	 * @return
	 */
	public static long getDiffMinutes(Date start, Date end) {
		long diffSeconds = getDiffSeconds(start, end);
		return diffSeconds/60;
	}

	/**
	 * @desc 比较两个时间相差多少天
	 * @param start 需要比较的开始时间
	 * @param end 需要比较的结束时间
	 * @return
	 */
	public static long getDiffDay(Date start, Date end) {
		long between = Math.abs((end.getTime() - start.getTime()) / 1000);
		long day = between / 60 / 60 / 24;
		return (long) Math.floor(day);
	}

	/**
	 * @desc 获取两个时间相差月份
	 * @param start 需要比较的开始时间
	 * @param end 需要比较的结束时间
	 * @return
	 */
	public static int getDiffMonth(Date start, Date end) {
		Calendar startCalendar = Calendar.getInstance();
		startCalendar.setTime(start);
		Calendar endCalendar = Calendar.getInstance();
		endCalendar.setTime(end);
		return (endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR)) * 12
				+ endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
	}

	/**
	 * @desc 格式化日期为日期字符串
	 * @param date 时间对象
	 * @param patterns 指定的时间格式
	 * @return 指定格式的时间字符串
	 */
	public static String format(Date date, String... patterns) {
		if (date == null) {
			return "";
		}

		String pattern = TIMESTAMP_PATTERN;
		if (patterns != null && patterns.length > 0
				&& org.apache.commons.lang3.StringUtils.isNotBlank(patterns[0])) {
			pattern = patterns[0];
		}
		return DateFormatUtils.format(date, pattern);
	}

	/**
	 * @desc 格式化日期为指定格式
	 * @param orig 需要格式化的时间对象
	 * @param patterns 日期格式
	 * @return Date
	 */
	public static Date formatDate(Date orig, String... patterns) {
		if (orig == null) {
			return null;
		}

		String pattern = TIMESTAMP_PATTERN;
		if (patterns != null && patterns.length > 0
				&& StringUtils.isNotBlank(patterns[0])) {
			pattern = patterns[0];
		}
		return parseDate(DateFormatUtils.format(orig, pattern));
	}

	/**
	 * @desc 格式化日期字符串
	 * @param dateStr 日期字符串
	 * @param patterns 日期格式
	 * @return
	 */
	public static String formatDateStr(String dateStr, String... patterns) {
		String pattern = TIMESTAMP_PATTERN;
		if (patterns != null && patterns.length > 0
				&& StringUtils.isNotBlank(patterns[0])) {
			pattern = patterns[0];
		}
		return DateFormatUtils.format(parseDate(dateStr), pattern);
	}

	/**
	 * @desc 格式化日期为日期字符串
	 * @param date 时间对象
	 * @param patterns 日期格式
	 * @return
	 */
	public static String format2DateStr(Date date, String... patterns) {
		if (date == null) {
			return "";
		}

		String pattern = TIMESTAMP_PATTERN;
		if (patterns != null && patterns.length > 0
				&& StringUtils.isNotBlank(patterns[0])) {
			pattern = patterns[0];
		}
		return DateFormatUtils.format(date, pattern);
	}

	/**
	 * @desc 时间戳格式转换为日期（年月日 yyyy-MM-dd）格式
	 * @param date 时间戳格式时间对象
	 * @return
	 */
	public static Date timestamp2Date(Date date) {
		return formatDate(date, DATE_PATTERN);
	}

	/**
	 * @desc 按照指定的时间格式,解析日期获取对应的格式后的时间对象
	 * @param formater 支持的时间格式
	 * @return Date
	 */
	public static Date parseDate(String formater) {
		SimpleDateFormat format;
		if (StringUtils.isBlank(formater)) {
			return null;
		}

		formater = formater.trim();
		try {
			if (formater.matches("\\d{1,2}[A-Z]{3}")) {
				formater = formater
						+ (Calendar.getInstance().get(Calendar.YEAR) - 2000);
			}
			// 01OCT12
			if (formater.matches("\\d{1,2}[A-Z]{3}\\d{2}")) {
				format = new SimpleDateFormat("ddMMMyy", Locale.ENGLISH);
			} else if (formater.matches("\\d{1,2}[A-Z]{3}\\d{4}.*")) {
				// 01OCT2012,01OCT2012 1224,01OCT2012 12:24
				formater = formater.replaceAll("[^0-9A-Z]", "")
						.concat("000000").substring(0, 15);
				format = new SimpleDateFormat("ddMMMyyyyHHmmss", Locale.ENGLISH);
			} else {
				StringBuffer sb = new StringBuffer(formater);
				String[] tempArr = formater.split("\\s+");
				tempArr = tempArr[0].split("-|\\/");
				if (tempArr.length == 3) {
					if (tempArr[1].length() == 1) {
						sb.insert(5, "0");
					}
					if (tempArr[2].length() == 1) {
						sb.insert(8, "0");
					}
				}
				formater = sb.append("000000").toString().replaceAll("[^0-9]",
						"").substring(0, 14);
				if (formater.matches("\\d{14}")) {
					format = new SimpleDateFormat("yyyyMMddHHmmss");
				} else {
					format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				}
			}
			return format.parse(formater);
		} catch (Exception e) {
			throw new RuntimeException("无法解析日期字符[" + formater + "]");
		}
	}
}